home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / savecopy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-31  |  14.3 KB  |  459 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: savecopy.c,v 5.12 1993/05/31 19:35:24 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.12 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1988-1992 USENET Community Trust
  8.  *             Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: savecopy.c,v $
  17.  * Revision 5.12  1993/05/31  19:35:24  syd
  18.  * Move the actual file saving code out of "save_copy()" into a seperate
  19.  * routine called "append_copy_to_file()" to make it globally available.
  20.  * In particular the "Canceled.mail" handling is going to be rewritten
  21.  * to use it.
  22.  * From: chip@chinacat.unicom.com (Chip Rosenthal)
  23.  *
  24.  * Revision 5.11  1993/05/08  20:25:33  syd
  25.  * Add sleepmsg to control transient message delays
  26.  * From: Syd
  27.  *
  28.  * Revision 5.10  1993/04/12  02:34:36  syd
  29.  * I have now added a parameter which controls whether want_to clears the
  30.  * line and centers the question or behaves like it did before. I also
  31.  * added a 0 at the end of the parameter list to all the other calls to
  32.  * want_to where a centered question on a clean line is not desirable.
  33.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  34.  *
  35.  * Revision 5.9  1993/02/03  17:12:53  syd
  36.  * move more declarations to defs.h, including sleep
  37.  * From: Syd
  38.  *
  39.  * Revision 5.8  1993/01/19  04:55:10  syd
  40.  * fix which file name is used on confirm messages
  41.  * From: vogt@isa.de (Gerald Vogt)
  42.  *
  43.  * Revision 5.7  1993/01/19  03:55:39  syd
  44.  * exitprog.c makes a reference to a null character pointer, savecopy.c
  45.  * tries to reference an uninitialized variable, and the previous patch to
  46.  * src/lock.c to get rid of an uninitialized variable compiler message
  47.  * needed to be put in filter/lock.c as well.
  48.  * From: wdh@grouper.mkt.csd.harris.com (W. David Higgins)
  49.  *
  50.  * Revision 5.6  1992/12/25  00:18:10  syd
  51.  * Remove editing garbage from end
  52.  * From: Syd
  53.  *
  54.  * Revision 5.5  1992/12/24  21:42:01  syd
  55.  * Fix messages and nls messages to match.  Plus use want_to
  56.  * where appropriate.
  57.  * From: Syd, via prompting from Jan Djarv <Jan.Djarv@sa.erisoft.se>
  58.  *
  59.  * Revision 5.4  1992/11/26  00:46:50  syd
  60.  * Fix how errno is used so err is inited and used instead
  61.  * as errno gets overwritten by print system call
  62.  * From: Syd
  63.  *
  64.  * Revision 5.3  1992/10/30  21:01:49  syd
  65.  * More changes to folder creation confirmation
  66.  * From: Larry Philps <larryp@sco.COM>
  67.  *
  68.  * Revision 5.2  1992/10/24  13:25:41  syd
  69.  * In our global elm.rc I keep the four options as below
  70.  *
  71.  *     confirmappend = OFF    Don't confirm every append to any file.
  72.  *     confirmcreate = ON    Confirm creation of every new file.
  73.  *     confirmfiles = ON    Confirm append to non folder files though.
  74.  *     confirmfolders = ON    In case someone does not want to be asked
  75.  *                 every time when creating a new file try
  76.  *                 to confirm creation of folders though.
  77.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  78.  *
  79.  * Revision 5.1  1992/10/03  22:58:40  syd
  80.  * Initial checkin as of 2.4 Release at PL0
  81.  *
  82.  *
  83.  ******************************************************************************/
  84.  
  85. /** Save a copy of the specified message in a folder.
  86.  
  87. **/
  88.  
  89. #include "headers.h"
  90. #include "s_elm.h"
  91. #ifdef I_TIME
  92. #  include <time.h>
  93. #endif
  94. #ifdef I_SYSTIME
  95. #  include <sys/time.h>
  96. #endif
  97.  
  98. #include <errno.h>
  99.  
  100. char *format_long(), *error_description(), *ctime();
  101.  
  102. extern int errno;
  103.  
  104. #ifdef MIME
  105. extern int msg_is_multipart;
  106. #endif
  107. extern long C_L_Position[2];   /*To Remember position of the Content-Length*/
  108. extern long C_StartData[2];    /*To Remember length of Header Area */
  109. extern long C_EndData[2];   /* To Remeber the End of the Data */
  110.  
  111.  
  112. /*
  113.  * save_copy() - Append a copy of the message contained in "filename" to
  114.  * the file specified by "copy_file".  This routine simply gets all of
  115.  * the filenames right, and then invokes "append_copy_to_file()" to do
  116.  * the dirty work.
  117.  */
  118. save_copy(to, cc, bcc, filename, copy_file, form)
  119. char *to, *cc, *bcc, *filename, *copy_file;
  120. int form;
  121. {
  122.     char  buffer[SLEN],    /* read buffer                */
  123.           savename[SLEN],    /* name of file saving into    */
  124.           msg_buffer[SLEN], answer;
  125.     register int
  126.          is_ordinary_file;
  127.     int  err;
  128.   
  129.     /* presume copy_file is okay as is for now */
  130.     strcpy(savename, copy_file);
  131.  
  132.     /* if save-by-name wanted */
  133.     if((strcmp(copy_file, "=") == 0)  || (strcmp(copy_file, "=?") == 0)) {
  134.  
  135.       get_return_name(to, buffer, TRUE);    /* determine 'to' login */
  136.       if (strlen(buffer) == 0) {
  137.  
  138.         /* can't get file name from 'to' -- use sent_mail instead */
  139.         dprint(3, (debugfile,
  140.         "Warning: get_return_name couldn't break down %s\n", to));
  141.         error1(catgets(elm_msg_cat, ElmSet, ElmCannotDetermineToName,
  142. "Cannot determine `to' name to save by! Saving to \"sent\" folder %s instead."),
  143.           sent_mail);
  144.         strcpy(savename, "<");
  145.         if (sleepmsg > 0)
  146.         sleep(sleepmsg);
  147.       } else
  148.         sprintf(savename, "=%s", buffer);        /* good! */
  149.     }
  150.  
  151.     expand_filename(savename, TRUE);    /* expand special chars */
  152.  
  153.     /*
  154.      *  If saving conditionally by logname but folder doesn't
  155.      *  exist save to sent folder instead.
  156.      */
  157.     if((strcmp(copy_file, "=?") == 0)
  158.           && (access(savename, ACCESS_EXISTS) != 0)) {
  159.       dprint(5, (debugfile,
  160.         "Conditional save by name: file %s doesn't exist - using \"<\".\n",
  161.         savename));
  162.       strcpy(savename, "<");
  163.       expand_filename(savename, TRUE);
  164.     }
  165.  
  166.     /*
  167.      *  Allow options
  168.      *  confirm_files, confirm_folders,
  169.      *  confirm_append and confirm_create
  170.      *  to control where the actual copy
  171.      *  should be saved.
  172.      */
  173.     is_ordinary_file = strncmp (savename, folders, strlen(folders));
  174.  
  175.         if (access(savename, ACCESS_EXISTS)== 0) {    /* already there!! */
  176.         if (confirm_append || (confirm_files && is_ordinary_file)) {
  177.         /*
  178.          *  OK in batch mode it may be impossible
  179.          *  to ask the user to confirm. So we have
  180.          *  to use sent_mail anyway.
  181.          */
  182.         if (batch_only) {
  183.             strcpy(savename, sent_mail);
  184.         }
  185.         else {
  186.             if (is_ordinary_file)
  187.               MCsprintf(msg_buffer, catgets(elm_msg_cat, ElmSet, ElmConfirmFilesAppend,
  188.               "Append to an existing file `%s'? (%c/%c) "),
  189.             savename, *def_ans_yes, *def_ans_no);
  190.             else
  191.               MCsprintf(msg_buffer, catgets(elm_msg_cat, ElmSet, ElmConfirmFolderAppend,
  192.               "Append to mail folder `%s'? (%c/%c) "),
  193.             savename, *def_ans_yes, *def_ans_no);
  194.  
  195.             answer = want_to(msg_buffer, *def_ans_no, LINES-2, 1);
  196.  
  197.             if (answer != *def_ans_yes) {
  198.             strcpy(savename, sent_mail);
  199.             PutLine1 (LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSavingToInstead,
  200.                   "Alright - saving to `%s' instead"),
  201.                   savename);
  202.             if (sleepmsg > 0)
  203.                 sleep(sleepmsg);
  204.             ClearLine (LINES-2);
  205.             }
  206.         }
  207.         }
  208.     }
  209.         else {
  210.             if (confirm_create || (confirm_folders && !is_ordinary_file)) {
  211.         /*
  212.          *  OK in batch mode it may be impossible
  213.          *  to ask the user to confirm. So we have
  214.          *  to use sent_mail anyway.
  215.          */
  216.         if (batch_only) {
  217.             strcpy(savename, sent_mail);
  218.         }
  219.         else {
  220.             if (is_ordinary_file)
  221.               MCsprintf(msg_buffer, catgets(elm_msg_cat, ElmSet, ElmConfirmFilesCreate,
  222.               "Create a new file `%s'? (%c/%c) "),
  223.             savename, *def_ans_yes, *def_ans_no);
  224.             else
  225.               MCsprintf(msg_buffer, catgets(elm_msg_cat, ElmSet, ElmConfirmFolderCreate,
  226.               "Create a new mail folder `%s'? (%c/%c) "),
  227.             savename, *def_ans_yes, *def_ans_no);
  228.  
  229.             answer = want_to(msg_buffer, *def_ans_no, LINES-2, 1);
  230.  
  231.             if (answer != *def_ans_yes) {
  232.             strcpy(savename, sent_mail);
  233.             PutLine1 (LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSavingToInstead,
  234.                   "Alright - saving to `%s' instead"),
  235.                   savename);
  236.             if (sleepmsg > 0)
  237.                 sleep(sleepmsg);
  238.             ClearLine (LINES-2);
  239.             }
  240.         }
  241.         }
  242.     }
  243.  
  244.     if ((err = can_open(savename, "a"))) {
  245.       dprint(2, (debugfile,
  246.       "Error: attempt to autosave to a file that can't be appended to!\n"));
  247.       dprint(2, (debugfile, "\tfilename = \"%s\"\n", savename));
  248.       dprint(2, (debugfile, "** %s **\n", error_description(err)));
  249.  
  250.       /* Lets try sent_mail before giving up */
  251.       if(strcmp(sent_mail, savename) == 0) {
  252.         /* we are ALREADY using sent_mail! */
  253.         error1(catgets(elm_msg_cat, ElmSet, ElmCannotSaveTo,
  254.             "Cannot save to %s!"), savename);
  255.         if (sleepmsg > 0)
  256.             sleep(sleepmsg);
  257.         return(FALSE);
  258.       }
  259.  
  260.       if ((err = can_open(sent_mail, "a"))) {
  261.         dprint(2, (debugfile,
  262.       "Error: attempt to autosave to a file that can't be appended to!\n"));
  263.         dprint(2, (debugfile, "\tfilename = \"%s\"\n", sent_mail));
  264.         dprint(2, (debugfile, "** %s **\n", error_description(err)));
  265.         error2(catgets(elm_msg_cat, ElmSet, ElmCannotSaveToNorSent,
  266.             "Cannot save to %s nor to \"sent\" folder %s!"),
  267.             savename, sent_mail);
  268.         if (sleepmsg > 0)
  269.             sleep(sleepmsg);
  270.         return(FALSE);
  271.       }
  272.       error2(catgets(elm_msg_cat, ElmSet, ElmCannotSaveToSavingInstead,
  273.         "Cannot save to %s! Saving to \"sent\" folder %s instead."),
  274.             savename, sent_mail);
  275.       if (sleepmsg > 0)
  276.         sleep(sleepmsg);
  277.       strcpy(savename, sent_mail);
  278.     }
  279.  
  280.     return (append_copy_to_file(to, cc, bcc, savename, filename, form)==0);
  281. }
  282.  
  283. char *
  284. cf_english(fn)
  285. char *fn;
  286. {
  287.     /** Return "English" expansion for special copy file name abbreviations
  288.     or just the file name  **/
  289.  
  290.     if(!*fn)
  291.       return(catgets(elm_msg_cat, ElmSet, ElmNoSave, "<no save>"));
  292.     else if(!fn[1]) {
  293.       if(*fn == '=')
  294.     return(catgets(elm_msg_cat, ElmSet, ElmUncondSaveByName, "<unconditionally save by name>"));
  295.       else if(*fn == '<')
  296.     return(catgets(elm_msg_cat, ElmSet, ElmSentFolder, "<\"sent\" folder>"));
  297.     } else if ((fn[0] == '=') && (fn[1] == '?'))
  298.       return(catgets(elm_msg_cat, ElmSet, ElmCondSaveByName, "<conditionally save by name>"));
  299.  
  300.     return(fn);
  301. }
  302.  
  303. static char *ncf_prompt = NULL;
  304. int
  305. name_copy_file(fn)
  306. char *fn;
  307. {
  308.     /** Prompt user for name of file for saving copy of outbound msg to.
  309.     Return true if we need a redraw. **/
  310.  
  311.     int redraw = 0;    /* set when we ask for help = need redraw */
  312.     char buffer[SLEN], origbuffer[SLEN];
  313.     static char helpmsg[LONG_STRING];
  314.  
  315.  
  316.     if (ncf_prompt == NULL) {
  317.     ncf_prompt = catgets(elm_msg_cat, ElmSet, ElmSaveCopyInPrompt,
  318.             "Save copy in (use '?' for help/to list folders): ");
  319.     }
  320.     /* expand passed copy file name into English */
  321.     strcpy(buffer, cf_english(fn));
  322.  
  323.     /* prepare screen with instructions */
  324.     MoveCursor(LINES-2, 0);
  325.     CleartoEOS();
  326.     PutLine0(LINES-2, 0, ncf_prompt);
  327.  
  328.     while(1) {
  329.  
  330.       /* get file name from user input */
  331.       strcpy(origbuffer, buffer);
  332.       optionally_enter(buffer, LINES-2, strlen(ncf_prompt), FALSE, FALSE);
  333.  
  334.       if(strcmp(buffer, "?") != 0) { /* got what we wanted - non-help choice */
  335.  
  336.     if(strcmp(origbuffer, buffer) != 0)
  337.       /* user changed from our English expansion 
  338.        * so we'd better copy user input to fn
  339.        */
  340.       strcpy(fn, buffer);
  341.  
  342.     /* else user presumably left our English expansion - no change in fn */
  343.  
  344.     /* display English expansion of new user input a while */
  345.     PutLine1(LINES-2, strlen(ncf_prompt), cf_english(fn));
  346.     MoveCursor(LINES, 0);
  347.     if (sleepmsg > 0)
  348.         sleep((sleepmsg + 1) / 2);
  349.     MoveCursor(LINES-2, 0);
  350.     CleartoEOS();
  351.  
  352.     return(redraw);
  353.       }
  354.  
  355.       /* give help and list folders */
  356.       redraw = TRUE;
  357.       if(!*helpmsg) {    /* help message not yet formulated */
  358.     strcpy(helpmsg, catgets(elm_msg_cat, ElmSet, ElmListFoldersHelp1,
  359. "Enter: <nothing> to not save a copy of the message,\n\
  360. \r       '<'       to save in your \"sent\" folder ("));
  361.     strcat(helpmsg, sent_mail);
  362.     strcat(helpmsg, catgets(elm_msg_cat, ElmSet, ElmListFoldersHelp2,
  363. "),\n\
  364. \r       '='       to save by name (the folder name depends on whom the\n\
  365. \r                     message is to, in the end),\n\
  366. \r       '=?'      to save by name if the folder already exists,\n\
  367. \r                     and if not, to your \"sent\" folder,\n\
  368. \r       or a filename (a leading '=' denotes your folder directory).\n\r\n\r"));
  369.       }
  370.  
  371.       list_folders(4, helpmsg, NULL);
  372.       PutLine0(LINES-2, 0, ncf_prompt);
  373.  
  374.       /* restore as default to English version of the passed copy file name */
  375.       strcpy(buffer, cf_english(fn));
  376.  
  377.     }
  378. }
  379.  
  380.  
  381. int
  382. append_copy_to_file(to, cc, bcc, fname_copy, fname_mssg, form)
  383. char *to;
  384. char *cc;
  385. char *bcc;
  386. char *fname_copy;
  387. char *fname_mssg;
  388. int form;
  389. {
  390.     int err;
  391.     FILE *fp_copy, *fp_mssg;
  392.     extern FILE *write_header_info();
  393.  
  394.     /* open up the file with the message */
  395.     if ((fp_mssg = fopen(fname_mssg, "r")) == NULL) {
  396.     err = errno;
  397.     dprint(1, (debugfile,
  398.         "Error: Couldn't open \"%s\" for read in append_copy_to_file\n",
  399.         fname_mssg));
  400.     dprint(1, (debugfile, "** %s **\n", error_description(err)));
  401.     error1(catgets(elm_msg_cat, ElmSet, ElmAppendCopyCouldntReadFile,
  402.         "Couldn't read file \"%s\"!"), fname_mssg);
  403.     if (sleepmsg > 0)
  404.         sleep(sleepmsg);
  405.     return -1;
  406.     }
  407.  
  408.     /* dump the header to the end of the copy file */
  409.     save_file_stats(fname_copy);
  410.     fp_copy = write_header_info(fname_copy, to, cc, bcc, (form == YES), TRUE);
  411.     if (fp_copy == NULL) {
  412.     (void) fclose(fp_mssg);
  413.     return -1;
  414.     }
  415.     restore_file_stats(fname_copy);
  416.     C_StartData[0] = ftell(fp_copy);
  417.  
  418.     /* dump the contents of the message to the end of the copy file */
  419.     copy_message_across(fp_mssg, fp_copy, TRUE);
  420.  
  421. #ifdef MIME
  422.     if (!form != NO && msg_is_multipart) {
  423.     fprintf(fp_copy, "--%%#%%record%%#%%--\n");
  424.     if (C_L_Position[1] != 0L) {
  425.         C_EndData[1] = ftell(fp_copy);
  426.         C_L_Position[1] = fseek(fp_copy, C_L_Position[1], 0);
  427.         fprintf(fp_copy, "%d", C_EndData[1] - C_StartData[1]);
  428.         fseek(fp_copy, C_EndData[1], 0);
  429.     }
  430.     }
  431. #endif
  432.     C_EndData[0] = ftell(fp_copy) ;
  433.  
  434. #ifdef MMDF
  435.     /*
  436.      * Actually, the C_EndData just calculated is wrong for MMDF.
  437.      * Because we are saving a copy instead of handing off to
  438.      * submit, copy_message_across will have added the trailing
  439.      * MMDF MSG_SEPARATOR to the end of the saved message to ensure
  440.      * a valid mailbox format.  We *must not* count that
  441.      * MSG_SEPARATOR when calculating the size of the message for
  442.      * Content-Length header!  In order to keep the hack for this
  443.      * localized to this function, we will just subtract off the
  444.      * length of the MSG_SEPARATOR.
  445.      */
  446.     C_EndData[0] -= strlen(MSG_SEPARATOR);
  447. #endif /* MMDF */
  448.  
  449.     /* go fixup the content length header */
  450.     fseek(fp_copy, C_L_Position[0], 0);
  451.     fprintf(fp_copy, "%d", C_EndData[0] - C_StartData[0]);
  452.  
  453.     /* copy successfully done */
  454.     fclose(fp_copy);
  455.     fclose(fp_mssg);
  456.     return 0;
  457. }
  458.  
  459.